home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Documentation / d e v e l o p / Develop Issue 23 article / Geometry Sample / Shell src / wprintf.c < prev   
Encoding:
C/C++ Source or Header  |  1997-08-14  |  12.7 KB  |  469 lines  |  [TEXT/MPS ]

  1.  
  2. #include "BuildControl.h"
  3.  
  4.  
  5.  
  6. #if defined(qUseDumpFile)
  7.     #include "DumpHeader.h"
  8. #else
  9.     #include <Memory.h>
  10.     #include <AppleEvents.h>
  11. #endif
  12.  
  13.  
  14. #include <stdio.h>
  15. #include <stdarg.h>
  16. #include <string.h>
  17.  
  18. #include "wprintf.h"
  19.  
  20.  
  21.  
  22. //
  23. // ------- private stuff -------
  24. //
  25.  
  26. #define kWindowAppSig            'MOOS'
  27. #define kConsoleDisplayClass    'Kons'
  28. #define kDumpMemoryEvent        'Dmem'
  29. #define kShowStringEvent        'Sstr'
  30.  
  31.  
  32. void    AESendString        (char *str);
  33. OSErr    DBGCreateAETarget    (OSType targetSig, AEDesc *targetDesc);
  34. void    GetMemoryDump        (Boolean wantDumpHeader, 
  35.                               Handle *textHandle, Ptr startingAddr, 
  36.                              long *numberOfBytes);
  37. long    Draw1Space            (char *buffer);
  38. long    Draw4CharHex        (char *buffer, unsigned short thisWord);
  39. long    DrawAddrLocation    (char *buffer, Ptr addrLocation);
  40. long     DrawASCIIDump        (char *buffer, Ptr startAddr);
  41. long     Draw16ByteLine        (char *buffer, Ptr startAddr);
  42. long    GetDumpHeader        (char *buffer, Ptr startingAddr, long numberOfBytes);
  43.  
  44.  
  45.  
  46.  
  47. //----------------------------------------------------------------------------
  48. // wprintf
  49. //
  50. // str should probably be a global if you're not building standalone code, 
  51. // because sucking up 1K of stack could be bad.
  52. //----------------------------------------------------------------------------
  53. #pragma segment AESupport
  54. void wprintf(const char *format, ...)
  55. {
  56.     va_list        arg;
  57.     long        len;
  58.     char        str[1024];
  59.  
  60.     va_start(arg, format);
  61.     len = (long) vsprintf(str, format, arg);
  62.     va_end(arg);
  63.  
  64.     if (len > 0)
  65.         AESendString(str);
  66. }
  67.  
  68.  
  69. //----------------------------------------------------------------------------
  70. // wprintmem
  71. //----------------------------------------------------------------------------
  72. #pragma segment AESupport
  73. void wprintmem(Ptr startingAddr, Size numberOfBytes)
  74. {
  75.     OSErr            err;
  76.     AppleEvent        theAppleEvent, theReplyEvent;
  77.     AEDesc            target;
  78.     long            returnedBytes;
  79.     Handle            textHandle;
  80.  
  81.     target.dataHandle            = NULL;
  82.     theAppleEvent.dataHandle     = NULL;
  83.  
  84.     err = DBGCreateAETarget(kWindowAppSig, &target);
  85.  
  86.     if (err == noErr) {
  87.         err = AECreateAppleEvent(kConsoleDisplayClass, kDumpMemoryEvent,
  88.             &target, kAutoGenerateReturnID, kAnyTransactionID,
  89.             &theAppleEvent);
  90.     
  91.         returnedBytes = (long) numberOfBytes;
  92.         GetMemoryDump(true, &textHandle, startingAddr, &returnedBytes);
  93.  
  94.         if (textHandle != NULL) {
  95.             //
  96.             // We have a text handle filled with the memory requested.
  97.             // Put it in the Apple Event as keyDirectObject.
  98.             //
  99.             HLock(textHandle);
  100.             err = AEPutParamPtr(&theAppleEvent, keyDirectObject, typeChar, 
  101.                                     *textHandle, returnedBytes);
  102.             HUnlock(textHandle);
  103.             DisposeHandle(textHandle);
  104.  
  105.             if (err == noErr)
  106.                 (void) AESend(&theAppleEvent, &theReplyEvent, kAENoReply, 
  107.                                 kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  108.         }
  109.     }
  110.     
  111.     //
  112.     // Dispose of everything that was allocated    
  113.     //
  114.     if (theAppleEvent.dataHandle != NULL)     (void) AEDisposeDesc(&theAppleEvent);
  115.     if (target.dataHandle != NULL)             (void) AEDisposeDesc(&target);
  116.  
  117. }
  118.  
  119.  
  120. //----------------------------------------------------------------------------
  121. // DBGCreateAETarget
  122. //----------------------------------------------------------------------------
  123. #pragma segment AESupport
  124. static OSErr DBGCreateAETarget(OSType targetSig, AEDesc *targetDesc)
  125. {
  126.     return AECreateDesc(typeApplSignature, &targetSig, sizeof(OSType), targetDesc);
  127. }
  128.  
  129.  
  130. //----------------------------------------------------------------------------
  131. // AESendString
  132. //----------------------------------------------------------------------------
  133. #pragma segment AESupport
  134. static void AESendString(char *str)
  135. {
  136.     OSErr            err;
  137.     AppleEvent        theAppleEvent, theReplyEvent;
  138.     AEDesc            target;
  139.     
  140.     target.dataHandle            = NULL;
  141.     theAppleEvent.dataHandle     = NULL;
  142.  
  143.     err = DBGCreateAETarget(kWindowAppSig, &target);
  144.  
  145.     if (err == noErr) {
  146.         err = AECreateAppleEvent(kConsoleDisplayClass, kShowStringEvent,
  147.             &target, kAutoGenerateReturnID, kAnyTransactionID,
  148.             &theAppleEvent);
  149.         
  150.         if (err == noErr) {
  151.             err = AEPutParamPtr(&theAppleEvent, keyDirectObject, typeChar,
  152.                                  str, strlen(str));
  153.         
  154.             if (err == noErr)
  155.                 (void) AESend(&theAppleEvent, &theReplyEvent, kAENoReply, 
  156.                                 kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  157.         }
  158.     }
  159.     
  160.     //
  161.     // Dispose of everything that was allocated    
  162.     //
  163.     if (theAppleEvent.dataHandle != NULL)     (void) AEDisposeDesc(&theAppleEvent);
  164.     if (target.dataHandle != NULL)             (void) AEDisposeDesc(&target);
  165.  
  166. }
  167.  
  168.  
  169. //----------------------------------------------------------------------------
  170. // •• Memory Display code ••
  171. //----------------------------------------------------------------------------
  172.  
  173. static char pNumCharTable[16] = {    '0', '1', '2', '3', '4', '5', '6', '7', 
  174.                                     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  175.  
  176.  
  177. //----------------------------------------------------------------------------
  178. // FailNULL
  179. //----------------------------------------------------------------------------
  180. static void FailNULL(void *addr)
  181. {
  182.     if (addr == NULL)  Debugger();
  183. }
  184.  
  185.  
  186. //----------------------------------------------------------------------------
  187. // Draw1Space
  188. //
  189. // Fills buffer with one space at the beginning of buffer
  190. //
  191. // RETURNS        the number of characters added to buffer (in this case 1)
  192. //----------------------------------------------------------------------------
  193. static long Draw1Space(char *buffer)
  194. {
  195.     FailNULL(buffer);
  196.     buffer[0] = ' ';
  197.     return 1;
  198. }
  199.  
  200.  
  201. //----------------------------------------------------------------------------
  202. // Draw4CharHex
  203. //
  204. // Fills buffer with a textual display of the specified word in the form:
  205. //
  206. // XXXX
  207. //
  208. // at address startAddr.
  209. //
  210. // RETURNS        the number of characters added to buffer (in this case 4)
  211. //----------------------------------------------------------------------------
  212. static long Draw4CharHex(char *buffer, unsigned short thisWord)
  213. {
  214.     short    count;
  215.     unsigned short    mask[4] = {0xF000, 0x0F00, 0x00F0, 0x000F};
  216.     unsigned short    shift[4] = {12, 8, 4, 0};
  217.     unsigned short    tmpShort;
  218.  
  219.     FailNULL(buffer);
  220.  
  221.     for (count = 0; count < 4; count ++) {
  222.         tmpShort = thisWord & mask[count];
  223.         tmpShort >>= shift[count];
  224.         buffer[count] = pNumCharTable[tmpShort];
  225.     }
  226.     return 4;
  227. }
  228.  
  229.  
  230. //----------------------------------------------------------------------------
  231. // DrawAddrLocation
  232. //
  233. // Fills buffer with a textual display of the specified address in the form:
  234. //
  235. // AAAAAAAA
  236. //
  237. // at address startAddr.
  238. //
  239. // RETURNS        the number of characters added to buffer
  240. //----------------------------------------------------------------------------
  241. static long DrawAddrLocation(char *buffer, Ptr addrLocation)
  242. {
  243.     unsigned long displayLong;
  244.     unsigned short    displayWord;
  245.     long    bufferPos = 0;
  246.  
  247.     displayLong = (unsigned long)addrLocation;
  248.  
  249.     // Draw the high word of the long
  250.     displayWord = (unsigned short)(displayLong >> 16);
  251.     bufferPos += Draw4CharHex(&buffer[bufferPos], displayWord);
  252.  
  253.     // Draw the low word of the long
  254.     displayWord = (unsigned short)(displayLong & 0xFFFF);
  255.     bufferPos += Draw4CharHex(&buffer[bufferPos], displayWord);
  256.  
  257.     return bufferPos;
  258. }
  259.  
  260.  
  261. //----------------------------------------------------------------------------
  262. // DrawASCIIDump
  263. //
  264. // Fills buffer with a display of 16 bytes of memory in ASCII in the form:
  265. //
  266. // 'ASCIIASCIIASCIIA'
  267. //
  268. // starting at address startAddr.  Characters greater than 0xDA and less
  269. // than 0x20 are shown as '–' instead.
  270. //
  271. // RETURNS        the number of characters added to buffer
  272. //----------------------------------------------------------------------------
  273. static long DrawASCIIDump(char *buffer, Ptr startAddr)
  274. {
  275.     long     bufferPos = 0;
  276.     long    counter;
  277.  
  278.     // Put in the single quotes with the memory dump in between
  279.     buffer[bufferPos] = '\'';
  280.     BlockMoveData(startAddr, &buffer[1], 16);
  281.     bufferPos += 17;
  282.     buffer[bufferPos] = '\'';
  283.     bufferPos ++;
  284.     
  285.     // Now scan the line for goofy characters, and replace any of them
  286.     // with a '–' (option-dash).
  287.     for (counter = 0; counter < bufferPos; counter ++) {
  288.         if (((unsigned char)buffer[counter] < 0x20) 
  289.                 || ((unsigned char)buffer[counter] >= 0xDA))
  290.             buffer[counter] = '–';
  291.     }
  292.     
  293.     return bufferPos;
  294. }
  295.  
  296.  
  297. //----------------------------------------------------------------------------
  298. // Draw16ByteLine
  299. //
  300. // Fills buffer with a textual display of 16 bytes of memory in the form:
  301. //
  302. // AAAAAAAA   NNNN NNNN NNNN NNNN  NNNN NNNN NNNN NNNN  'ASCIIASCIIASCIIA'\n
  303. //
  304. // starting at address startAddr.
  305. //
  306. // RETURNS        the number of characters added to buffer
  307. //----------------------------------------------------------------------------
  308. static long Draw16ByteLine(char *buffer, Ptr startAddr)
  309. {
  310.     long    bufferPos = 0, incAddress = 0;
  311.     unsigned long displayLong;
  312.     unsigned short displayWord;
  313.     short    x, y;
  314.  
  315.     bufferPos += DrawAddrLocation(&buffer[bufferPos], startAddr);
  316.  
  317.     // Put in two spaces;
  318.     bufferPos += Draw1Space(&buffer[bufferPos]);
  319.     bufferPos += Draw1Space(&buffer[bufferPos]);
  320.     
  321.     for ( y = 0; y < 2; y ++) {
  322.         for (x = 0; x < 2; x ++) {
  323.             // Fetch the address to start from
  324.             displayLong = *(unsigned long *)(startAddr + incAddress);
  325.         
  326.             // Draw the high word of the long
  327.             displayWord = (unsigned short)(displayLong >> 16);
  328.             bufferPos += Draw4CharHex(&buffer[bufferPos], displayWord);
  329.     
  330.             // Put in a space
  331.             bufferPos += Draw1Space(&buffer[bufferPos]);
  332.     
  333.             // Draw the low word of the long
  334.             displayWord = (unsigned short)(displayLong & 0xFFFF);
  335.             bufferPos += Draw4CharHex(&buffer[bufferPos], displayWord);
  336.     
  337.             // Put in a space
  338.             bufferPos += Draw1Space(&buffer[bufferPos]);
  339.             
  340.             incAddress += 4;
  341.         }
  342.         // To put in a space after every two longs
  343.         bufferPos += Draw1Space(&buffer[bufferPos]);
  344.     }
  345.     
  346.     // Get the ASCII dump, and the newline at the end.
  347.     bufferPos += DrawASCIIDump(&buffer[bufferPos], startAddr);
  348. #ifdef __MWERKS__
  349.     buffer[bufferPos] = 13; 
  350. #else
  351.     buffer[bufferPos] = '\n'; 
  352. #endif
  353.     bufferPos += 1;
  354.  
  355.     return bufferPos;
  356.  
  357. }
  358.  
  359.  
  360. //----------------------------------------------------------------------------
  361. // GetDumpHeader
  362. //
  363. // Fills buffer with text showing information about to be dumped in the form:
  364. //
  365. // Dumping DDD bytes starting at location 0xHHHHHHHH:\n\n
  366. //
  367. // RETURNS        the number of characters added to buffer
  368. //----------------------------------------------------------------------------
  369. static long GetDumpHeader(    char    *buffer,
  370.                             Ptr        startingAddr,
  371.                             long    numberOfBytes)
  372. {
  373.     long bufferPos;
  374.     Str32 tmpBytes;
  375.     Str32    dumpText = "\pDumping ";
  376.     Str32    startingAtLocText = "\p bytes starting at location 0x";
  377.  
  378.     if (buffer == NULL)   Debugger();
  379.  
  380.     bufferPos = 0;
  381.     
  382.     // Put in the "Dumping" message
  383.     BlockMoveData(&dumpText[1], &buffer[bufferPos], dumpText[0]);
  384.     bufferPos += dumpText[0];
  385.     
  386.     // Put in the number of bytes to be dumped
  387.     NumToString((long)numberOfBytes, tmpBytes);
  388.     BlockMoveData(&tmpBytes[1], &buffer[bufferPos], tmpBytes[0]);
  389.     bufferPos += tmpBytes[0];
  390.     
  391.     // Put in the second message
  392.     BlockMoveData(&startingAtLocText[1], &buffer[bufferPos], startingAtLocText[0]);
  393.     bufferPos += startingAtLocText[0];
  394.  
  395.     // Put in the starting addr location
  396.     bufferPos += DrawAddrLocation(&buffer[bufferPos], startingAddr);
  397.     
  398.     // Put in the two newlines
  399.     buffer[bufferPos] = '\n'; 
  400.     bufferPos += 1;
  401.  
  402.     buffer[bufferPos] = '\n'; 
  403.     bufferPos += 1;
  404.  
  405.     // return the number of bytes filled
  406.     return bufferPos;
  407. }
  408.  
  409.  
  410. //----------------------------------------------------------------------------
  411. // GetMemoryDump
  412. //
  413. // Allocates a Handle for a text dump of memory at location startingAddr, 
  414. // and a size of numberOfBytes.
  415. //
  416. // INPUT:
  417. //        textHandle    
  418. //                    pointer to a Handle that will be allocated by the
  419. //                    routine, which will contain text dump if successful,
  420. //                    or NULL if not.
  421. //
  422. //        startingAddr
  423. //                    address of the first byte to be dumped.
  424. //
  425. //        numberOfBytes
  426. //                    on entry, the number of bytes to be dumped.  On exit,
  427. //                    this contains the actual size of the dumped memory.
  428. //                    numberOfBytes will be rounded up to the amount of  
  429. //                    memory needed to display the nearest multiple of 16
  430. //                    bytes, since that's the amount of memory.  Example:
  431. //                        -> numberOfBytes = 1
  432. //                        <- numberOfBytes = 71, since it takes 71 bytes to
  433. //                                display a line of memory.
  434. //----------------------------------------------------------------------------
  435. static void GetMemoryDump(    Boolean        wantDumpHeader,
  436.                             Handle        *textHandle,
  437.                             Ptr            startingAddr,
  438.                             long        *numberOfBytes)
  439. {
  440.     long         lineSize;
  441.     Handle        theText;
  442.     char        buffer[71];
  443.     long        textLen = 0;
  444.     short        count;
  445.     short        timesThroughLoop;
  446.     
  447.     timesThroughLoop = (*numberOfBytes / 16) + 1;
  448.     theText = NewHandle(0);
  449.  
  450.     if (theText != NULL) {
  451.         // Put in the header if they want it
  452.         if (wantDumpHeader == true) {
  453.             lineSize = GetDumpHeader(&buffer[0], startingAddr, *numberOfBytes);
  454.             SetHandleSize(theText, textLen + lineSize);
  455.             BlockMoveData(&buffer[0], &(*theText)[textLen], lineSize);
  456.             textLen += lineSize;
  457.         }
  458.     
  459.         for (count = 0; count < timesThroughLoop; count++) {
  460.             lineSize = Draw16ByteLine(&buffer[0], (Ptr)((16 * count) + startingAddr));
  461.             SetHandleSize(theText, textLen + lineSize);
  462.             BlockMoveData(&buffer[0], &(*theText)[textLen], lineSize);
  463.             textLen += lineSize;
  464.         }
  465.     }
  466.  
  467.     *numberOfBytes = textLen;
  468.     *textHandle = theText;
  469. }